package com.per.mybootall.es;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.per.mybootall.common.TableEnum;
import com.per.mybootall.config.SpringContextHolder;
import com.per.mybootall.pojo.CanalUser;
import com.per.mybootall.pojo.ElasticSearchHighPo;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class ElasticSearchHighUtils {

@Resource
private RestHighLevelClient restHighLevelClient;

private String prefix="order_optimize_";
Logger log= LoggerFactory.getLogger(ElasticSearchHighUtils.class);
/**
 * 创建索引 【创建myIndex空索引】
 * */
    public  void creatIndex(RestHighLevelClient restHighLevelClient,String tableName) throws IOException {
        System.out.println("创建索引==》》》");
        //创建索引请求    myIndex是索引的名字
        CreateIndexRequest createIndexRequest=new CreateIndexRequest(prefix+tableName);
        //客户端执行请求 indices create ,请求后获得响应
        CreateIndexResponse createIndexResponse=restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);

        System.out.println(createIndexResponse);
    }


    /**
     * 向索引中创建mapping映射
     * */
    public void creatMapping(RestHighLevelClient restHighLevelClient,String tableName) throws IOException {
        CreateIndexRequest createIndexRequest=new CreateIndexRequest(prefix+tableName);
        TableEnum type= TableEnum.getEnumByName(tableName);
        createIndexRequest.mapping(type.getMapping());
        CreateIndexResponse res = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        System.out.println(tableName+"映射创建成功："+res.toString());
    }


    public boolean testIndexExist(RestHighLevelClient restHighLevelClient,String tableName) throws IOException {
        GetIndexRequest request=new GetIndexRequest(prefix+tableName);
        boolean res= restHighLevelClient.indices().exists(request,RequestOptions.DEFAULT);
        System.out.println("该索引是否存在："+res);
        return res;
    }

    /**
     * 删除索引
     * */
    public void testDelectIndex(RestHighLevelClient restHighLevelClient) throws IOException {
        System.out.println("删除索引==》》》");
        //构建删除请求
        DeleteIndexRequest deleteIndexRequest=new DeleteIndexRequest("test_canal_user");
        //通过restHighLevelClient发送删除请求
        AcknowledgedResponse ack= restHighLevelClient.indices().delete(deleteIndexRequest,RequestOptions.DEFAULT);
        //通过删除返回的ack判断是否删除成功
        System.out.println(ack.isAcknowledged());
    }


    /**
     * 向索引中添加文档
     * */
    public void testAddDocument(RestHighLevelClient restHighLevelClient, Map afterData,String tableName) throws IOException {
        IndexRequest indexRequest=new IndexRequest(prefix+tableName);
        indexRequest.source(afterData, XContentType.JSON);
        indexRequest.id(afterData.get("id").toString());
        indexRequest.timeout(TimeValue.timeValueSeconds(1));
        IndexResponse indexResponse=restHighLevelClient.index(indexRequest,RequestOptions.DEFAULT);
        System.out.println(indexResponse.status());
        if(indexResponse.getResult().name().equalsIgnoreCase("created")){
            log.error("创建文档成功");
        }else {
            log.error("创建文档失败");
        }
    }


    /**
     * 判断文档是否存在
     * */
    public void testIsExist(RestHighLevelClient restHighLevelClient) throws IOException {
        System.out.println("判断文档是否存在==》》》");
        GetRequest getRequest=new GetRequest("test_canal_user","1");
        //设置不获取_source的上下文了
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        getRequest.storedFields("_none_");
        //通过restHighLevelClient发送请求，返回文档是否存在
        boolean isExist= restHighLevelClient.exists(getRequest,RequestOptions.DEFAULT);
        System.out.println("该文档是否存在的结果为："+isExist);
    }



    /**
     * 获取文档的信息
     * */
    public void testGetDocument(RestHighLevelClient restHighLevelClient,Map afterMap) throws IOException {
        //构建请求信息
        GetRequest getRequest=new GetRequest("test_canal_user",afterMap.get("id").toString());
        //通过restHighLevelClient 发送请求，并获取响应信息
        GetResponse getResponse=restHighLevelClient.get(getRequest,RequestOptions.DEFAULT);
        //打印文档的内容
        System.out.println("获取文档信息==》》》"+getResponse.getSourceAsString());
        //打印响应
        System.out.println(getResponse);
    }



    /**
     * 更新文档信息
     * */
    public  void testUpdateRequest(RestHighLevelClient restHighLevelClient,Map afterMap,String tableName) throws IOException {
        System.out.println("更新文档信息==》》》");
        //创建更新的请求
        UpdateRequest updateRequest=new UpdateRequest(prefix+tableName,afterMap.get("id").toString());
        //设置超时时间
        updateRequest.timeout("1s");
        //将更新的数据以json格式放入请求中
        updateRequest.doc(afterMap,XContentType.JSON);
        //通过restHighLevelClient 发送更新请求
        UpdateResponse up=restHighLevelClient.update(updateRequest,RequestOptions.DEFAULT);
        //获取更新后的状态
        System.out.println(up.status());
    }


    /**
     * 删除文档记录
     * */
    public void testDelectDocument(RestHighLevelClient restHighLevelClient,Map beforeMap,String tableName) throws IOException {
        System.out.println("删除文档记录==》》》");
        //构造删除的请求  【前提是先要有文档id为2的文档】
        DeleteRequest deleteRequest=new DeleteRequest(prefix+tableName,beforeMap.get("id").toString());
        //deleteRequest.timeout("1s");
        //通过restHighLevelClient 发送删除请求，并获取对应的响应数据
        DeleteResponse deleteResponse=restHighLevelClient.delete(deleteRequest,RequestOptions.DEFAULT);

        System.out.println(deleteResponse.status());
    }


    /**
     * 向索引中批量插入数据
     * */
    public void testBulkRequest(RestHighLevelClient restHighLevelClient) throws IOException {
        System.out.println("向索引批量插入==》》》");
        //构建批量请求对象
        BulkRequest bulkRequest=new BulkRequest();
        //设置该对象的超时时间
        bulkRequest.timeout("10s");

        //构建需要插入的批量数据
        List<CanalUser> list=new ArrayList<>();
        for(int a=0;a<10;a++){
            list.add(new CanalUser());
        }

        //将需要批量插入的数据add进批量请求的对象中
        for(int i=0;i<list.size();i++){
            //指定批量请求对象插入的是哪一个索引
            bulkRequest.add(new IndexRequest("test_canal_user")
                    //设置该文档的id
                    .id(String.valueOf(i+3))
                    //将批量数据以json格式存入请求对象中
                    .source(JSON.toJSON(list.get(i)),XContentType.JSON));
        }
        //通过restHighLevelClient 发送批量请求对象，并获取其响应数据
        BulkResponse  bulk=restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
        //打印是否执行失败 【返回布尔值，是否失败】
        System.out.println(bulk.hasFailures());
    }


    /**
     * 批量更新
     * */
    public void testBulkUpdateRequest() throws IOException {
        //构建批量请求对象
        BulkRequest bulkRequest=new BulkRequest();

        //设置该对象的超时时间
        bulkRequest.timeout("10s");
        //bulkRequest.update
        //构建需要插入的批量数据
        List<CanalUser> list=new ArrayList<>();
        for(int a=0;a<10;a++){
            list.add(new CanalUser());
        }

        //将需要批量插入的数据add进批量请求的对象中
        for(int i=0;i<list.size();i++){
            //指定批量请求对象插入的是哪一个索引

                 //   bulkRequest
//            bulkRequest.add(new IndexRequest("myIndex")
//                    //设置该文档的id
//                    .id(String.valueOf(i+3))
//                    //将批量数据以json格式存入请求对象中
//                    .source(JSON.toJSON(list.get(i)),XContentType.JSON));
        }
        //通过restHighLevelClient 发送批量请求对象，并获取其响应数据
        BulkResponse  bulk=restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
        //打印是否执行失败 【返回布尔值，是否失败】
        System.out.println(bulk.hasFailures());
    }



    /**
     * 查询
     *          SearchRequest：搜索请求
     *          SearchSourceBuilder：条件构造
     *          sourceBuilder.highlighter() : 构建高亮
     *          sourceBuilder.from()  :  分页【起始】
     *          sourceBuilder.size()  :  分页【页size】
     * */
    public void testSearch(RestHighLevelClient restHighLevelClient,Map afterMap,String tableName) throws IOException {
        System.out.println("es查询==》》》");
        //索引对象
        SearchRequest searchContext=new SearchRequest(prefix+tableName);
        //搜索条件对象
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        /**
         * QueryBuilders.termQuery       ：   精确查询         【这里是精确匹配  user_name  为  “名字”  的数据】
         * QueryBuilders.matchAllQuery   :    分词匹配「模糊匹配」
         * */

        BoolQueryBuilder termQueryBuilder= QueryBuilders.boolQuery()
                .filter(QueryBuilders.matchQuery("id",afterMap.get("id")))
                .must(QueryBuilders.matchQuery("id",afterMap.get("id")));

        sourceBuilder.query(termQueryBuilder);

        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        searchContext.source(sourceBuilder);

        SearchResponse searchResponse=restHighLevelClient.search(searchContext,RequestOptions.DEFAULT);
        System.out.println(searchResponse.getHits());

        System.out.println("===========================================");
        for(SearchHit  documentFields: searchResponse.getHits().getHits()){
            System.out.println(documentFields.getSourceAsMap());
        }
    }


    /**
     * 多表连查
     * */
    public void testSearchByPage(Map params) throws IOException {
        if(restHighLevelClient==null){
            SpringContextHolder springContextHolder = new SpringContextHolder();
            restHighLevelClient = springContextHolder.getBean("restHighLevelClient", RestHighLevelClient.class);
        }

        SearchRequest userSearch=new SearchRequest(prefix+TableEnum.ODR_ORDER_GOODSORDER.getName());
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        BoolQueryBuilder termQueryBuilder= QueryBuilders.boolQuery();
        if(params.get("userName")!=null){
             termQueryBuilder= termQueryBuilder
                    .filter(QueryBuilders.matchQuery("user_name",params.get("user_name").toString()));
        }
        sourceBuilder.query(termQueryBuilder);
        userSearch.source(sourceBuilder);
        SearchResponse searchResponse=restHighLevelClient.search(userSearch,RequestOptions.DEFAULT);

        for(SearchHit  documentFields: searchResponse.getHits().getHits()){
            System.out.print("---"+documentFields.getSourceAsMap().get("user_name"));


        }
    }

}
